home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Demos / ByCompany / TipTop_Software / TipTop / Supplement / src / Z301 / rz.c < prev    next >
Text File  |  1994-05-08  |  33KB  |  1,589 lines

  1. #define VERSION "3.01 5-25-89"
  2. #define PUBDIR "/usr/spool/uucppublic"
  3.  
  4. /*% cc -compat -M2 -Ox -K -i -DMD % -o rz; size rz;
  5. <-xtx-*> cc386 -Ox -DMD rz.c -o $B/rz;  size $B/rz
  6.  *
  7.  * rz.c By Chuck Forsberg
  8.  *
  9.  *    cc -O rz.c -o rz        USG (3.0) Unix
  10.  *     cc -O -DV7  rz.c -o rz        Unix V7, BSD 2.8 - 4.3
  11.  *
  12.  *    ln rz rb;  ln rz rx            For either system
  13.  *
  14.  *    ln rz /usr/bin/rzrmail        For remote mail.  Make this the
  15.  *                    login shell. rzrmail then calls
  16.  *                    rmail(1) to deliver mail.
  17.  *
  18.  * To compile on VMS:
  19.  *
  20.  *    define LNK$LIBRARY   SYS$LIBRARY:VAXCRTL.OLB
  21.  *    cc rz.c
  22.  *    cc vvmodem.c
  23.  *    link rz,vvmodem
  24.  *    rz :== $disk:[username.subdir]rz.exe
  25.  *      For high speed, try increasing the SYSGEN parameter TTY_TYPAHDSZ to 256.
  26.  *
  27.  *
  28.  *  Unix is a trademark of Western Electric Company
  29.  *
  30.  * A program for Unix to receive files and commands from computers running
  31.  *  Professional-YAM, PowerCom, YAM, IMP, or programs supporting XMODEM.
  32.  *  rz uses Unix buffered input to reduce wasted CPU time.
  33.  *
  34.  *    This version implements ZMODEM Run Length Encoding 
  35.  *    and variable length headers.  These features were not funded
  36.  *    by the original Telenet development contract.  This software,
  37.  *    including these features, may be freely used for non
  38.  *    commercial and educational purposes.  This software may also
  39.  *    be freely used to support file transfer operations to or from
  40.  *    licensed Omen Technology products.  Contact Omen Technology
  41.  *    for licensing for other uses.  Any programs which use part or
  42.  *    all of this software must be provided in source form with this
  43.  *    notice intact except by written permission from Omen
  44.  *    Technology Incorporated.
  45.  *
  46.  *        Omen Technology Inc        FAX: 503-621-3745
  47.  *        Post Office Box 4681
  48.  *        Portland OR 97208
  49.  *
  50.  *    Previous versions of this program (not containing the extensions
  51.  *    listed above) remain in the public domain.
  52.  *
  53.  *    This code is made available in the hope it will be useful,
  54.  *    BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
  55.  *    DAMAGES OF ANY KIND.
  56.  *
  57.  *
  58.  * Iff the program is invoked by rzCOMMAND, output is piped to 
  59.  * "COMMAND filename"  (Unix only)
  60.  *
  61.  *  Some systems (Venix, Coherent, Regulus) may not support tty raw mode
  62.  *  read(2) the same way as Unix. ONEREAD must be defined to force one
  63.  *  character reads for these systems. Added 7-01-84 CAF
  64.  *
  65.  *  Alarm signal handling changed to work with 4.2 BSD 7-15-84 CAF 
  66.  *
  67.  *  BIX added 6-30-87 to support BIX(TM) upload protocol used by the
  68.  *  Byte Information Exchange.
  69.  *
  70.  *  NFGVMIN Updated 2-18-87 CAF for Xenix systems where c_cc[VMIN]
  71.  *  doesn't work properly (even though it compiles without error!),
  72.  *
  73.  *  SEGMENTS=n added 2-21-88 as a model for CP/M programs
  74.  *    for CP/M-80 systems that cannot overlap modem and disk I/O.
  75.  *
  76.  *  VMS flavor hacks begin with rz version 2.00
  77.  *
  78.  *  -DMD may be added to compiler command line to compile in
  79.  *    Directory-creating routines from Public Domain TAR by John Gilmore
  80.  *
  81.  *  HOWMANY may be tuned for best performance
  82.  *
  83.  *  USG UNIX (3.0) ioctl conventions courtesy  Jeff Martin
  84.  */
  85.  
  86.  
  87. #ifdef NeXT
  88. #import <objc/objc.h>
  89. #import "TransferProgressProtocol.h"
  90. id getProgressListener();
  91. static id remote;
  92. #endif
  93.  
  94. #ifdef vax11c
  95. #include <types.h>
  96. #include <stat.h>
  97. #define LOGFILE "rzlog.tmp"
  98. #include <stdio.h>
  99. #include <signal.h>
  100. #include <setjmp.h>
  101. #include <ctype.h>
  102. #include <errno.h>
  103. #define OS "VMS"
  104. #define BUFREAD
  105. extern int errno;
  106. #define SS_NORMAL SS$_NORMAL
  107.  
  108. #ifndef PROGNAME
  109. #define PROGNAME "rz"
  110. #endif
  111.  
  112.  
  113. #else
  114.  
  115.  
  116. #define SS_NORMAL 0
  117. #define LOGFILE "/tmp/rzlog"
  118. #include <stdio.h>
  119. #include <signal.h>
  120. #include <setjmp.h>
  121. #include <ctype.h>
  122. #include <errno.h>
  123. extern int errno;
  124. FILE *popen();
  125. #endif
  126.  
  127. #define OK 0
  128. #ifdef FALSE
  129. #undef FALSE
  130. #endif
  131. #define FALSE 0
  132. #ifdef TRUE
  133. #undef TRUE
  134. #endif
  135. #define TRUE 1
  136. #define ERROR (-1)
  137.  
  138. /*
  139.  * Max value for HOWMANY is 255.
  140.  *   A larger value reduces system overhead but may evoke kernel bugs.
  141.  *   133 corresponds to an XMODEM/CRC sector
  142.  */
  143. #ifndef HOWMANY
  144. #define HOWMANY 133
  145. #endif
  146.  
  147. /* Ward Christensen / CP/M parameters - Don't change these! */
  148. #define ENQ 005
  149. #define CAN ('X'&037)
  150. #define XOFF ('s'&037)
  151. #define XON ('q'&037)
  152. #define SOH 1
  153. #define STX 2
  154. #define EOT 4
  155. #define ACK 6
  156. #define NAK 025
  157. #define CPMEOF 032
  158. #define WANTCRC 0103    /* send C not NAK to get crc not checksum */
  159. #define TIMEOUT (-2)
  160. #define RCDO (-3)
  161. #define GCOUNT (-4)
  162. #define ERRORMAX 5
  163. #define RETRYMAX 5
  164. #define WCEOT (-10)
  165. #define PATHLEN 257    /* ready for 4.2 bsd ? */
  166. #define UNIXFILE 0xF000    /* The S_IFMT file mask bit for stat */
  167.  
  168. int Zmodem=0;        /* ZMODEM protocol requested */
  169. int Nozmodem = 0;    /* If invoked as "rb" */
  170. unsigned Baudrate = 2400;
  171. unsigned Effbaud = 2400;
  172. #ifdef vax11c
  173. #include "vrzsz.c"    /* most of the system dependent stuff here */
  174. #else
  175. #include "rbsb.c"    /* most of the system dependent stuff here */
  176. #endif
  177. #include "crctab.c"
  178.  
  179. char *substr();
  180. FILE *fout;
  181.  
  182. /*
  183.  * Routine to calculate the free bytes on the current file system
  184.  *  ~0 means many free bytes (unknown)
  185.  */
  186. long getfree()
  187. {
  188.     return(~0L);    /* many free bytes ... */
  189. }
  190.  
  191. int Lastrx;
  192. int Crcflg;
  193. int Firstsec;
  194. int Eofseen;        /* indicates cpm eof (^Z) has been received */
  195. int errors;
  196. int Restricted=0;    /* restricted; no /.. or ../ in filenames */
  197. #ifdef ONEREAD
  198. /* Sorry, Regulus and some others don't work right in raw mode! */
  199. int Readnum = 1;    /* Number of bytes to ask for in read() from modem */
  200. #else
  201. int Readnum = HOWMANY;    /* Number of bytes to ask for in read() from modem */
  202. #endif
  203.  
  204. #define DEFBYTL 2000000000L    /* default rx file size */
  205. long Bytesleft;        /* number of bytes of incoming file left */
  206. long Modtime;        /* Unix style mod time for incoming file */
  207. int Filemode;        /* Unix style mode for incoming file */
  208. char Pathname[PATHLEN];
  209. char *Progname;        /* the name by which we were called */
  210.  
  211. int Batch=0;
  212. int Topipe=0;
  213. int MakeLCPathname=TRUE;    /* make received pathname lower case */
  214. int Verbose=0;
  215. int Quiet=0;        /* overrides logic that would otherwise set verbose */
  216. int Nflag = 0;        /* Don't really transfer files */
  217. int Rxclob=FALSE;    /* Clobber existing file */
  218. int Rxbinary=FALSE;    /* receive all files in bin mode */
  219. int Rxascii=FALSE;    /* receive files in ascii (translate) mode */
  220. int Thisbinary;        /* current file is to be received in bin mode */
  221. int Blklen;        /* record length of received packets */
  222.  
  223. #ifdef SEGMENTS
  224. int chinseg = 0;    /* Number of characters received in this data seg */
  225. char secbuf[1+(SEGMENTS+1)*1024];
  226. #else
  227. char secbuf[1025];
  228. #endif
  229.  
  230.  
  231. char linbuf[HOWMANY];
  232. int Lleft=0;        /* number of characters in linbuf */
  233. time_t timep[2];
  234. char Lzmanag;        /* Local file management request */
  235. char zconv;        /* ZMODEM file conversion request */
  236. char zmanag;        /* ZMODEM file management request */
  237. char ztrans;        /* ZMODEM file transport request */
  238. int Zctlesc;        /* Encode control characters */
  239. int Zrwindow = 1400;    /* RX window size (controls garbage count) */
  240.  
  241. jmp_buf tohere;        /* For the interrupt on RX timeout */
  242.  
  243. #define xsendline(c) sendline(c)
  244.  
  245. #include "zm.c"
  246.  
  247. #include "zmr.c"
  248.  
  249. int tryzhdrtype=ZRINIT;    /* Header type to send corresponding to Last rx close */
  250.  
  251. alrm()
  252. {
  253.     longjmp(tohere, -1);
  254. }
  255.  
  256. /* called by signal interrupt or terminate to clean things up */
  257. bibi(n)
  258. {
  259.     if (Zmodem)
  260.         zmputs(Attn);
  261.     canit(); mode(0);
  262.     fprintf(stderr, "rz: caught signal %d; exiting", n);
  263. #ifdef NeXT
  264.     { char buf[50];
  265.       sprintf(buf,"Caught signal %d; exiting",n);
  266.       [remote transferMessage:buf];
  267.       sleep(1);
  268.       [remote transferEnd];
  269.     }
  270. #endif
  271.     cucheck();
  272.     exit(128+n);
  273. }
  274.  
  275. main(argc, argv)
  276. char *argv[];
  277. {
  278.     register char *cp;
  279.     register npats;
  280.     char *virgin, **patts;
  281.     char *getenv();
  282.     int exitcode;
  283.  
  284.     Rxtimeout = 100;
  285.     setbuf(stderr, NULL);
  286.     if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
  287.         Restricted=TRUE;
  288.  
  289.     from_cu();
  290. #ifdef vax11c
  291.     chkinvok(virgin = PROGNAME);
  292. #else
  293.     chkinvok(virgin=argv[0]);    /* if called as [-]rzCOMMAND set flag */
  294. #endif
  295.     inittty();
  296.     npats = 0;
  297.     while (--argc) {
  298.         cp = *++argv;
  299.         if (*cp == '-') {
  300.             while( *++cp) {
  301.                 switch(*cp) {
  302.                 case '\\':
  303.                      cp[1] = toupper(cp[1]);  continue;
  304.                 case '+':
  305.                     Lzmanag = ZMAPND; break;
  306.                 case 'a':
  307.                     Rxascii=TRUE;  break;
  308.                 case 'b':
  309.                     Rxbinary=TRUE; break;
  310.                 case 'c':
  311.                     Crcflg=TRUE; break;
  312. #ifndef vax11c
  313.                 case 'D':
  314.                     Nflag = TRUE; break;
  315. #endif
  316.                 case 'e':
  317.                     Zctlesc = 1; break;
  318.                 case 'p':
  319.                     Lzmanag = ZMPROT;  break;
  320.                 case 'q':
  321.                     Quiet=TRUE; Verbose=0; break;
  322.                 case 't':
  323.                     if (--argc < 1) {
  324.                         usage();
  325.                     }
  326.                     Rxtimeout = atoi(*++argv);
  327.                     if (Rxtimeout<10 || Rxtimeout>1000)
  328.                         usage();
  329.                     break;
  330.                 case 'w':
  331.                     if (--argc < 1) {
  332.                         usage();
  333.                     }
  334.                     Zrwindow = atoi(*++argv);
  335.                     break;
  336.                 case 'u':
  337.                     MakeLCPathname=FALSE; break;
  338.                 case 'v':
  339.                     ++Verbose; break;
  340.                 case 'y':
  341.                     Rxclob=TRUE; break;
  342.                 default:
  343.                     usage();
  344.                 }
  345.             }
  346.         }
  347.         else if ( !npats && argc>0) {
  348.             if (argv[0][0]) {
  349.                 npats=argc;
  350.                 patts=argv;
  351.             }
  352.         }
  353.     }
  354.     if (npats > 1)
  355.         usage();
  356.     if (Batch && npats)
  357.         usage();
  358.     if (Verbose) {
  359.         if (freopen(LOGFILE, "a", stderr)==NULL) {
  360.             printf("Can't open log file %s\n",LOGFILE);
  361.             exit(0200);
  362.         }
  363.         setbuf(stderr, NULL);
  364.         fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname);
  365.     }
  366.     if (Fromcu && !Quiet) {
  367.         if (Verbose == 0)
  368.             Verbose = 2;
  369.     }
  370.     vfile("%s %s for %s\n", Progname, VERSION, OS);
  371.     mode(1);
  372.     if (signal(SIGINT, bibi) == SIG_IGN) {
  373.         signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
  374.     }
  375.     else {
  376.         signal(SIGINT, bibi); signal(SIGKILL, bibi);
  377.     }
  378.     signal(SIGTERM, bibi);
  379. #ifdef NeXT
  380.     [remote transferBegin:!Batch?"XMODEM Receive"
  381.                     :(Nozmodem?"YMODEM Receive"
  382.                           :"ZMODEM Receive")];
  383. #endif
  384.     if (wcreceive(npats, patts)==ERROR) {
  385.         exitcode=0200;
  386.         canit();
  387.     }
  388.     mode(0);
  389.     if (exitcode && !Zmodem)    /* bellow again with all thy might. */
  390.         canit();
  391.     if (exitcode)
  392.         cucheck();
  393. #ifdef NeXT
  394.     [remote transferEnd];
  395. #endif
  396.     exit(exitcode ? exitcode:SS_NORMAL);
  397. }
  398.  
  399.  
  400. usage()
  401. {
  402.     cucheck();
  403.     fprintf(stderr,"Usage:    rz [-abeuvy]        (ZMODEM)\n");
  404.     fprintf(stderr,"or    rb [-abuvy]        (YMODEM)\n");
  405.     fprintf(stderr,"or    rx [-abcv] file    (XMODEM or XMODEM-1k)\n");
  406.     fprintf(stderr,"      -a ASCII transfer (strip CR)\n");
  407.     fprintf(stderr,"      -b Binary transfer for all files\n");
  408. #ifndef vax11c
  409.     fprintf(stderr,"      -c Use 16 bit CRC    (XMODEM)\n");
  410. #endif
  411.     fprintf(stderr,"      -e Escape control characters    (ZMODEM)\n");
  412.     fprintf(stderr,"      -v Verbose more v's give more info\n");
  413.     fprintf(stderr,"      -y Yes, clobber existing file if any\n");
  414.     fprintf(stderr,"%s %s for %s by Chuck Forsberg, Omen Technology INC\n",
  415.       Progname, VERSION, OS);
  416.     fprintf(stderr, "\t\t\042The High Reliability Software\042\n");
  417.     exit(SS_NORMAL);
  418. }
  419. /*
  420.  *  Debugging information output interface routine
  421.  */
  422. /* VARARGS1 */
  423. vfile(f, a, b, c)
  424. register char *f;
  425. {
  426.     if (Verbose > 2) {
  427.         fprintf(stderr, f, a, b, c);
  428.         fprintf(stderr, "\n");
  429.     }
  430. }
  431.  
  432. /*
  433.  * Let's receive something already.
  434.  */
  435.  
  436. char *rbmsg =
  437. "%s ready. To begin transfer, type \"%s file ...\" to your modem program\r\n\n";
  438.  
  439. wcreceive(argc, argp)
  440. char **argp;
  441. {
  442.     register c;
  443.  
  444.     if (Batch || argc==0) {
  445.         Crcflg=1;
  446.         if ( !Quiet)
  447.             fprintf(stderr, rbmsg, Progname, Nozmodem?"sb":"sz");
  448.         if (c=tryz()) {
  449.             if (c == ZCOMPL)
  450.                 return OK;
  451.             if (c == ERROR)
  452.                 goto fubar;
  453.             c = rzfiles();
  454.             if (c)
  455.                 goto fubar;
  456.         } else {
  457.             for (;;) {
  458.                 if (wcrxpn(secbuf)== ERROR)
  459.                     goto fubar;
  460.                 if (secbuf[0]==0)
  461.                     return OK;
  462.                 if (procheader(secbuf) == ERROR)
  463.                     goto fubar;
  464.                 if (wcrx()==ERROR)
  465.                     goto fubar;
  466.             }
  467.         }
  468.     } else {
  469.         Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
  470.  
  471.         procheader(""); strcpy(Pathname, *argp); checkpath(Pathname);
  472. #ifdef NeXT
  473.         [remote transferFileBegin:Pathname];
  474. #endif
  475.  
  476.         fprintf(stderr, "\nrz: ready to receive %s\r\n", Pathname);
  477.         if ((fout=fopen(Pathname, "w")) == NULL)
  478.             return ERROR;
  479.         if (wcrx()==ERROR)
  480.             goto fubar;
  481.     }
  482.     return OK;
  483. fubar:
  484.     canit();
  485. #ifndef vax11c
  486.     if (Topipe && fout) {
  487.         pclose(fout);  return ERROR;
  488.     }
  489. #endif
  490.     Modtime = 1;
  491.     if (fout)
  492.         fclose(fout);
  493. #ifndef vax11c
  494.     if (Restricted) {
  495.         unlink(Pathname);
  496.         fprintf(stderr, "\r\nrz: %s removed.\r\n", Pathname);
  497.     }
  498. #endif
  499.     return ERROR;
  500. }
  501.  
  502.  
  503. /*
  504.  * Fetch a pathname from the other end as a C ctyle ASCIZ string.
  505.  * Length is indeterminate as long as less than Blklen
  506.  * A null string represents no more files (YMODEM)
  507.  */
  508. wcrxpn(rpn)
  509. char *rpn;    /* receive a pathname */
  510. {
  511.     register c;
  512.  
  513. #ifdef NFGVMIN
  514.     readline(1);
  515. #else
  516.     purgeline();
  517. #endif
  518.  
  519. et_tu:
  520.     Firstsec=TRUE;  Eofseen=FALSE;
  521.     sendline(Crcflg?WANTCRC:NAK);
  522.     Lleft=0;    /* Do read next time ... */
  523.     while ((c = wcgetsec(rpn, 100)) != 0) {
  524.         if (c == WCEOT) {
  525.             zperr( "Pathname fetch returned %d", c);
  526.             sendline(ACK);
  527.             Lleft=0;    /* Do read next time ... */
  528.             readline(1);
  529.             goto et_tu;
  530.         }
  531.         return ERROR;
  532.     }
  533.     sendline(ACK);
  534.     return OK;
  535. }
  536.  
  537. /*
  538.  * Adapted from CMODEM13.C, written by
  539.  * Jack M. Wierda and Roderick W. Hart
  540.  */
  541.  
  542. wcrx()
  543. {
  544.     register int sectnum, sectcurr;
  545.     register char sendchar;
  546.     register char *p;
  547.     int cblklen;            /* bytes to dump this block */
  548.  
  549.     Firstsec=TRUE;sectnum=0; Eofseen=FALSE;
  550.     sendchar=Crcflg?WANTCRC:NAK;
  551.  
  552.     for (;;) {
  553.         sendline(sendchar);    /* send it now, we're ready! */
  554.         Lleft=0;    /* Do read next time ... */
  555.         sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130);
  556.         report(sectcurr);
  557.         if (sectcurr==(sectnum+1 &0377)) {
  558.             sectnum++;
  559.             cblklen = Bytesleft>Blklen ? Blklen:Bytesleft;
  560.             if (putsec(secbuf, cblklen)==ERROR)
  561.                 return ERROR;
  562.             if ((Bytesleft-=cblklen) < 0)
  563.                 Bytesleft = 0;
  564.             sendchar=ACK;
  565.         }
  566.         else if (sectcurr==(sectnum&0377)) {
  567.             zperr( "Received dup Sector");
  568.             sendchar=ACK;
  569.         }
  570.         else if (sectcurr==WCEOT) {
  571.             if (closeit())
  572.                 return ERROR;
  573.             sendline(ACK);
  574.             Lleft=0;    /* Do read next time ... */
  575.             return OK;
  576.         }
  577.         else if (sectcurr==ERROR)
  578.             return ERROR;
  579.         else {
  580.             zperr( "Sync Error");
  581.             return ERROR;
  582.         }
  583.     }
  584. }
  585.  
  586. /*
  587.  * Wcgetsec fetches a Ward Christensen type sector.
  588.  * Returns sector number encountered or ERROR if valid sector not received,
  589.  * or CAN CAN received
  590.  * or WCEOT if eot sector
  591.  * time is timeout for first char, set to 4 seconds thereafter
  592.  ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
  593.  *    (Caller must do that when he is good and ready to get next sector)
  594.  */
  595.  
  596. wcgetsec(rxbuf, maxtime)
  597. char *rxbuf;
  598. int maxtime;
  599. {
  600.     register checksum, wcj, firstch;
  601.     register unsigned short oldcrc;
  602.     register char *p;
  603.     int sectcurr;
  604.  
  605.     for (Lastrx=errors=0; errors<RETRYMAX; errors++) {
  606.  
  607.         if ((firstch=readline(maxtime))==STX) {
  608.             Blklen=1024; goto get2;
  609.         }
  610.         if (firstch==SOH) {
  611.             Blklen=128;
  612. get2:
  613.             sectcurr=readline(1);
  614.             if ((sectcurr+(oldcrc=readline(1)))==0377) {
  615.                 oldcrc=checksum=0;
  616.                 for (p=rxbuf,wcj=Blklen; --wcj>=0; ) {
  617.                     if ((firstch=readline(1)) < 0)
  618.                         goto bilge;
  619.                     oldcrc=updcrc(firstch, oldcrc);
  620.                     checksum += (*p++ = firstch);
  621.                 }
  622.                 if ((firstch=readline(1)) < 0)
  623.                     goto bilge;
  624.                 if (Crcflg) {
  625.                     oldcrc=updcrc(firstch, oldcrc);
  626.                     if ((firstch=readline(1)) < 0)
  627.                         goto bilge;
  628.                     oldcrc=updcrc(firstch, oldcrc);
  629.                     if (oldcrc & 0xFFFF)
  630.                         zperr( "CRC");
  631.                     else {
  632.                         Firstsec=FALSE;
  633.                         return sectcurr;
  634.                     }
  635.                 }
  636.                 else if (((checksum-firstch)&0377)==0) {
  637.                     Firstsec=FALSE;
  638.                     return sectcurr;
  639.                 }
  640.                 else
  641.                     zperr( "Checksum");
  642.             }
  643.             else
  644.                 zperr("Sector number garbled");
  645.         }
  646.         /* make sure eot really is eot and not just mixmash */
  647. #ifdef NFGVMIN
  648.         else if (firstch==EOT && readline(1)==TIMEOUT)
  649.             return WCEOT;
  650. #else
  651.         else if (firstch==EOT && Lleft==0)
  652.             return WCEOT;
  653. #endif
  654.         else if (firstch==CAN) {
  655.             if (Lastrx==CAN) {
  656.                 zperr( "Sender CANcelled");
  657.                 return ERROR;
  658.             } else {
  659.                 Lastrx=CAN;
  660.                 continue;
  661.             }
  662.         }
  663.         else if (firstch==TIMEOUT) {
  664.             if (Firstsec)
  665.                 goto humbug;
  666. bilge:
  667.             zperr( "TIMEOUT");
  668.         }
  669.         else
  670.             zperr( "Got 0%o sector header", firstch);
  671.  
  672. humbug:
  673.         Lastrx=0;
  674.         while(readline(1)!=TIMEOUT)
  675.             ;
  676.         if (Firstsec) {
  677.             sendline(Crcflg?WANTCRC:NAK);
  678.             Lleft=0;    /* Do read next time ... */
  679.         } else {
  680.             maxtime=40; sendline(NAK);
  681.             Lleft=0;    /* Do read next time ... */
  682.         }
  683.     }
  684.     /* try to stop the bubble machine. */
  685.     canit();
  686.     return ERROR;
  687. }
  688.  
  689. #ifndef vax11c
  690. /*
  691.  * This version of readline is reasoably well suited for
  692.  * reading many characters.
  693.  *  (except, currently, for the Regulus version!)
  694.  *
  695.  * timeout is in tenths of seconds
  696.  */
  697. readline(timeout)
  698. int timeout;
  699. {
  700.     register n;
  701.     static char *cdq;    /* pointer for removing chars from linbuf */
  702.  
  703.     if (--Lleft >= 0) {
  704.         if (Verbose > 8) {
  705.             fprintf(stderr, "%02x ", *cdq&0377);
  706.         }
  707.         return (*cdq++ & 0377);
  708.     }
  709.     n = timeout/10;
  710.     if (n < 2)
  711.         n = 3;
  712.     if (Verbose > 5)
  713.         fprintf(stderr, "Calling read: alarm=%d  Readnum=%d ",
  714.           n, Readnum);
  715.     if (setjmp(tohere)) {
  716. #ifdef TIOCFLUSH
  717. /*        ioctl(0, TIOCFLUSH, 0); */
  718. #endif
  719.         Lleft = 0;
  720.         if (Verbose>1)
  721.             fprintf(stderr, "Readline:TIMEOUT\n");
  722.         return TIMEOUT;
  723.     }
  724.     signal(SIGALRM, alrm); alarm(n);
  725.     Lleft=read(0, cdq=linbuf, Readnum);
  726.     alarm(0);
  727.     if (Verbose > 5) {
  728.         fprintf(stderr, "Read returned %d bytes\n", Lleft);
  729.     }
  730.     if (Lleft < 1)
  731.         return TIMEOUT;
  732.     --Lleft;
  733.     if (Verbose > 8) {
  734.         fprintf(stderr, "%02x ", *cdq&0377);
  735.     }
  736.     return (*cdq++ & 0377);
  737. }
  738.  
  739.  
  740.  
  741. /*
  742.  * Purge the modem input queue of all characters
  743.  */
  744. purgeline()
  745. {
  746.     Lleft = 0;
  747. #ifdef USG
  748.     ioctl(0, TCFLSH, 0);
  749. #else
  750.     lseek(0, 0L, 2);
  751. #endif
  752. }
  753. #endif
  754.  
  755.  
  756. /*
  757.  * Process incoming file information header
  758.  */
  759. procheader(name)
  760. char *name;
  761. {
  762.     register char *openmode, *p, **pp;
  763.  
  764.     /* set default parameters and overrides */
  765.     openmode = "w";
  766.     Thisbinary = (!Rxascii) || Rxbinary;
  767.     if (Lzmanag)
  768.         zmanag = Lzmanag;
  769.  
  770.     /*
  771.      *  Process ZMODEM remote file management requests
  772.      */
  773.     if (!Rxbinary && zconv == ZCNL)    /* Remote ASCII override */
  774.         Thisbinary = 0;
  775.     if (zconv == ZCBIN)    /* Remote Binary override */
  776.         Thisbinary = TRUE;
  777.     else if (zmanag == ZMAPND)
  778.         openmode = "a";
  779.  
  780. #ifndef BIX
  781.     /* Check for existing file */
  782.     if (!Rxclob && (zmanag&ZMMASK) != ZMCLOB && (fout=fopen(name, "r"))) {
  783.         fclose(fout);  return ERROR;
  784.     }
  785. #endif
  786.  
  787.     Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
  788.  
  789.     p = name + 1 + strlen(name);
  790.     if (*p) {    /* file coming from Unix or DOS system */
  791.         sscanf(p, "%ld%lo%o", &Bytesleft, &Modtime, &Filemode);
  792. #ifndef vax11c
  793.         if (Filemode & UNIXFILE)
  794.             ++Thisbinary;
  795. #endif
  796. #ifdef NeXT
  797.         [remote transferFile:name size:Bytesleft];
  798. #endif
  799.         if (Verbose) {
  800.             fprintf(stderr,  "Incoming: %s %ld %lo %o\n",
  801.               name, Bytesleft, Modtime, Filemode);
  802.         }
  803.     }
  804.  
  805. #ifdef BIX
  806.     if ((fout=fopen("scratchpad", openmode)) == NULL)
  807.         return ERROR;
  808.     return OK;
  809. #else
  810.  
  811.     else {        /* File coming from CP/M system */
  812.         for (p=name; *p; ++p)        /* change / to _ */
  813.             if ( *p == '/')
  814.                 *p = '_';
  815.  
  816.         if ( *--p == '.')        /* zap trailing period */
  817.             *p = 0;
  818.     }
  819.  
  820. #ifndef vax11c
  821.     if (!Zmodem && MakeLCPathname && !IsAnyLower(name)
  822.       && !(Filemode&UNIXFILE))
  823.         uncaps(name);
  824. #endif
  825.     if (Topipe > 0) {
  826.         sprintf(Pathname, "%s %s", Progname+2, name);
  827.         if (Verbose)
  828.             fprintf(stderr,  "Topipe: %s %s\n",
  829.               Pathname, Thisbinary?"BIN":"ASCII");
  830. #ifndef vax11c
  831.         if ((fout=popen(Pathname, "w")) == NULL)
  832.             return ERROR;
  833. #endif
  834.     } else {
  835.         strcpy(Pathname, name);
  836.         if (Verbose) {
  837.             fprintf(stderr,  "Receiving %s %s %s\n",
  838.               name, Thisbinary?"BIN":"ASCII", openmode);
  839.         }
  840.         checkpath(name);
  841.         if (Nflag)
  842.             name = "/dev/null";
  843. #ifndef vax11c
  844.         if (name[0] == '!' || name[0] == '|') {
  845.             if ( !(fout = popen(name+1, "w"))) {
  846.                 return ERROR;
  847.             }
  848.             Topipe = -1;  return(OK);
  849.         }
  850. #endif
  851. #ifdef MD
  852.         fout = fopen(name, openmode);
  853.         if ( !fout)
  854.             if (make_dirs(name))
  855.                 fout = fopen(name, openmode);
  856. #else
  857.         fout = fopen(name, openmode);
  858. #endif
  859.         if ( !fout)
  860.             return ERROR;
  861.     }
  862.     return OK;
  863. #endif /* BIX */
  864. }
  865.  
  866. #ifdef MD
  867. /*
  868.  *  Directory-creating routines from Public Domain TAR by John Gilmore
  869.  */
  870.  
  871. /*
  872.  * After a file/link/symlink/dir creation has failed, see if
  873.  * it's because some required directory was not present, and if
  874.  * so, create all required dirs.
  875.  */
  876. make_dirs(pathname)
  877. register char *pathname;
  878. {
  879.     register char *p;        /* Points into path */
  880.     int madeone = 0;        /* Did we do anything yet? */
  881.     int save_errno = errno;        /* Remember caller's errno */
  882. #ifndef NeXT
  883.     char *strchr();
  884. #endif
  885.  
  886.     if (errno != ENOENT)
  887.         return 0;        /* Not our problem */
  888.  
  889.     for (p = strchr(pathname, '/'); p != NULL; p = strchr(p+1, '/')) {
  890.         /* Avoid mkdir of empty string, if leading or double '/' */
  891.         if (p == pathname || p[-1] == '/')
  892.             continue;
  893.         /* Avoid mkdir where last part of path is '.' */
  894.         if (p[-1] == '.' && (p == pathname+1 || p[-2] == '/'))
  895.             continue;
  896.         *p = 0;                /* Truncate the path there */
  897.         if ( !mkdir(pathname, 0777)) {    /* Try to create it as a dir */
  898.             vfile("Made directory %s\n", pathname);
  899.             madeone++;        /* Remember if we made one */
  900.             *p = '/';
  901.             continue;
  902.         }
  903.         *p = '/';
  904.         if (errno == EEXIST)        /* Directory already exists */
  905.             continue;
  906.         /*
  907.          * Some other error in the mkdir.  We return to the caller.
  908.          */
  909.         break;
  910.     }
  911.     errno = save_errno;        /* Restore caller's errno */
  912.     return madeone;            /* Tell them to retry if we made one */
  913. }
  914.  
  915. #if (MD != 2)
  916. #define    TERM_SIGNAL(status)    ((status) & 0x7F)
  917. #define TERM_COREDUMP(status)    (((status) & 0x80) != 0)
  918. #define TERM_VALUE(status)    ((status) >> 8)
  919. /*
  920.  * Make a directory.  Compatible with the mkdir() system call on 4.2BSD.
  921.  */
  922. mkdir(dpath, dmode)
  923. char *dpath;
  924. int dmode;
  925. {
  926.     int cpid, status;
  927.     struct stat statbuf;
  928.  
  929.     if (stat(dpath,&statbuf) == 0) {
  930.         errno = EEXIST;        /* Stat worked, so it already exists */
  931.         return -1;
  932.     }
  933.  
  934.     /* If stat fails for a reason other than non-existence, return error */
  935.     if (errno != ENOENT) return -1; 
  936.  
  937.     switch (cpid = fork()) {
  938.  
  939.     case -1:            /* Error in fork() */
  940.         return(-1);        /* Errno is set already */
  941.  
  942.     case 0:                /* Child process */
  943.         /*
  944.          * Cheap hack to set mode of new directory.  Since this
  945.          * child process is going away anyway, we zap its umask.
  946.          * FIXME, this won't suffice to set SUID, SGID, etc. on this
  947.          * directory.  Does anybody care?
  948.          */
  949.         status = umask(0);    /* Get current umask */
  950.         status = umask(status | (0777 & ~dmode)); /* Set for mkdir */
  951.         execl("/bin/mkdir", "mkdir", dpath, (char *)0);
  952.         _exit(-1);        /* Can't exec /bin/mkdir */
  953.     
  954.     default:            /* Parent process */
  955.         while (cpid != wait(&status)) ;    /* Wait for kid to finish */
  956.     }
  957.  
  958.     if (TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0) {
  959.         errno = EIO;        /* We don't know why, but */
  960.         return -1;        /* /bin/mkdir failed */
  961.     }
  962.  
  963.     return 0;
  964. }
  965. #endif /* MD != 2 */
  966. #endif /* MD */
  967.  
  968. /*
  969.  * Putsec writes the n characters of buf to receive file fout.
  970.  *  If not in binary mode, carriage returns, and all characters
  971.  *  starting with CPMEOF are discarded.
  972.  */
  973. putsec(buf, n)
  974. char *buf;
  975. register n;
  976. {
  977.     register char *p;
  978.  
  979.     if (n == 0)
  980.         return OK;
  981.     if (Thisbinary) {
  982.         for (p=buf; --n>=0; )
  983.             putc( *p++, fout);
  984.     }
  985.     else {
  986.         if (Eofseen)
  987.             return OK;
  988.         for (p=buf; --n>=0; ++p ) {
  989.             if ( *p == '\r')
  990.                 continue;
  991.             if (*p == CPMEOF) {
  992.                 Eofseen=TRUE; return OK;
  993.             }
  994.             putc(*p ,fout);
  995.         }
  996.     }
  997.     return OK;
  998. }
  999.  
  1000. #ifndef vax11c
  1001. /*
  1002.  *  Send a character to modem.  Small is beautiful.
  1003.  */
  1004. sendline(c)
  1005. {
  1006.     char d;
  1007.  
  1008.     d = c;
  1009.     if (Verbose>6)
  1010.         fprintf(stderr, "Sendline: %x\n", c);
  1011.     write(1, &d, 1);
  1012. }
  1013.  
  1014. flushmo() {}
  1015. #endif
  1016.  
  1017.  
  1018.  
  1019.  
  1020.  
  1021. /* make string s lower case */
  1022. uncaps(s)
  1023. register char *s;
  1024. {
  1025.     for ( ; *s; ++s)
  1026.         if (isupper(*s))
  1027.             *s = tolower(*s);
  1028. }
  1029. /*
  1030.  * IsAnyLower returns TRUE if string s has lower case letters.
  1031.  */
  1032. IsAnyLower(s)
  1033. register char *s;
  1034. {
  1035.     for ( ; *s; ++s)
  1036.         if (islower(*s))
  1037.             return TRUE;
  1038.     return FALSE;
  1039. }
  1040.  
  1041. /*
  1042.  * substr(string, token) searches for token in string s
  1043.  * returns pointer to token within string if found, NULL otherwise
  1044.  */
  1045. char *
  1046. substr(s, t)
  1047. register char *s,*t;
  1048. {
  1049.     register char *ss,*tt;
  1050.     /* search for first char of token */
  1051.     for (ss=s; *s; s++)
  1052.         if (*s == *t)
  1053.             /* compare token with substring */
  1054.             for (ss=s,tt=t; ;) {
  1055.                 if (*tt == 0)
  1056.                     return s;
  1057.                 if (*ss++ != *tt++)
  1058.                     break;
  1059.             }
  1060.     return NULL;
  1061. }
  1062.  
  1063. /*
  1064.  * Log an error
  1065.  */
  1066. /*VARARGS1*/
  1067. zperr(s,p,u)
  1068. char *s, *p, *u;
  1069. {
  1070.     if (Verbose <= 0)
  1071.         return;
  1072.     fprintf(stderr, "Retry %d: ", errors);
  1073.     fprintf(stderr, s, p, u);
  1074.     fprintf(stderr, "\n");
  1075. }
  1076.  
  1077. /* send cancel string to get the other end to shut up */
  1078. canit()
  1079. {
  1080.     static char canistr[] = {
  1081.      24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
  1082.     };
  1083.  
  1084. #ifdef vax11c
  1085.     raw_wbuf(strlen(canistr), canistr);
  1086.     purgeline();
  1087. #else
  1088.     printf(canistr);
  1089.     Lleft=0;    /* Do read next time ... */
  1090.     fflush(stdout);
  1091. #endif
  1092. }
  1093.  
  1094.  
  1095. report(sct)
  1096. int sct;
  1097. {
  1098. #ifdef NeXT
  1099.     [remote transferProgress:sct*Blklen];
  1100. #endif
  1101.     if (Verbose>1)
  1102.         fprintf(stderr,"%03d%c",sct,sct%10? ' ' : '\r');
  1103. }
  1104.  
  1105. /*
  1106.  * If called as [-][dir/../]vrzCOMMAND set Verbose to 1
  1107.  * If called as [-][dir/../]rzCOMMAND set the pipe flag
  1108.  * If called as rb use YMODEM protocol
  1109.  */
  1110. chkinvok(s)
  1111. char *s;
  1112. {
  1113.     register char *p;
  1114.  
  1115.     p = s;
  1116.     while (*p == '-')
  1117.         s = ++p;
  1118.     while (*p)
  1119.         if (*p++ == '/')
  1120.             s = p;
  1121.     if (*s == 'v') {
  1122.         Verbose=1; ++s;
  1123.     }
  1124.     Progname = s;
  1125.     if (s[0]=='r' && s[1]=='z')
  1126.         Batch = TRUE;
  1127.     if (s[0]=='r' && s[1]=='b')
  1128.         Batch = Nozmodem = TRUE;
  1129.     if (s[2] && s[0]=='r' && s[1]=='b')
  1130.         Topipe = 1;
  1131.     if (s[2] && s[0]=='r' && s[1]=='z')
  1132.         Topipe = 1;
  1133. }
  1134.  
  1135. /*
  1136.  * Totalitarian Communist pathname processing
  1137.  */
  1138. checkpath(name)
  1139. char *name;
  1140. {
  1141.     if (Restricted) {
  1142.         if (fopen(name, "r") != NULL) {
  1143.             canit();
  1144.             fprintf(stderr, "\r\nrz: %s exists\n", name);
  1145.             bibi(-1);
  1146.         }
  1147.         /* restrict pathnames to current tree or uucppublic */
  1148.         if ( substr(name, "../")
  1149.          || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {
  1150.             canit();
  1151.             fprintf(stderr,"\r\nrz:\tSecurity Violation\r\n");
  1152.             bibi(-1);
  1153.         }
  1154.     }
  1155. }
  1156.  
  1157. /*
  1158.  * Initialize for Zmodem receive attempt, try to activate Zmodem sender
  1159.  *  Handles ZSINIT frame
  1160.  *  Return ZFILE if Zmodem filename received, -1 on error,
  1161.  *   ZCOMPL if transaction finished,  else 0
  1162.  */
  1163. tryz()
  1164. {
  1165.     register c, n;
  1166.     register cmdzack1flg;
  1167.  
  1168.     if (Nozmodem)        /* Check for "rb" program name */
  1169.         return 0;
  1170.  
  1171.  
  1172.     for (n=Zmodem?15:5; --n>=0; ) {
  1173.         /* Set buffer length (0) and capability flags */
  1174. #ifdef SEGMENTS
  1175.         stohdr(SEGMENTS*1024L);
  1176. #else
  1177.         stohdr(0L);
  1178. #endif
  1179. #ifdef CANBREAK
  1180.         Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
  1181. #else
  1182.         Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;
  1183. #endif
  1184.         if (Zctlesc)
  1185.             Txhdr[ZF0] |= TESCCTL;
  1186.         Txhdr[ZF0] |= CANRLE;
  1187.         Txhdr[ZF1] = CANVHDR;
  1188.         /* tryzhdrtype may == ZRINIT */
  1189.         zshhdr(4,tryzhdrtype, Txhdr);
  1190.         if (tryzhdrtype == ZSKIP)    /* Don't skip too far */
  1191.             tryzhdrtype = ZRINIT;    /* CAF 8-21-87 */
  1192. again:
  1193.         switch (zgethdr(Rxhdr, 0)) {
  1194.         case ZRQINIT:
  1195.             if (Rxhdr[ZF3] & 0x80)
  1196.                 Usevhdrs = 1;    /* we can var header */
  1197.             continue;
  1198.         case ZEOF:
  1199.             continue;
  1200.         case TIMEOUT:
  1201.             continue;
  1202.         case ZFILE:
  1203.             zconv = Rxhdr[ZF0];
  1204.             zmanag = Rxhdr[ZF1];
  1205.             ztrans = Rxhdr[ZF2];
  1206.             if (Rxhdr[ZF3] & ZCANVHDR)
  1207.                 Usevhdrs = TRUE;
  1208.             tryzhdrtype = ZRINIT;
  1209.             c = zrdata(secbuf, 1024);
  1210.             mode(3);
  1211.             if (c == GOTCRCW)
  1212.                 return ZFILE;
  1213.             zshhdr(4,ZNAK, Txhdr);
  1214.             goto again;
  1215.         case ZSINIT:
  1216.             Zctlesc = TESCCTL & Rxhdr[ZF0];
  1217.             if (zrdata(Attn, ZATTNLEN) == GOTCRCW) {
  1218.                 stohdr(1L);
  1219.                 zshhdr(4,ZACK, Txhdr);
  1220.                 goto again;
  1221.             }
  1222.             zshhdr(4,ZNAK, Txhdr);
  1223.             goto again;
  1224.         case ZFREECNT:
  1225.             stohdr(getfree());
  1226.             zshhdr(4,ZACK, Txhdr);
  1227.             goto again;
  1228.         case ZCOMMAND:
  1229. #ifdef vax11c
  1230.             return ERROR;
  1231. #else
  1232.             cmdzack1flg = Rxhdr[ZF0];
  1233.             if (zrdata(secbuf, 1024) == GOTCRCW) {
  1234.                 if (cmdzack1flg & ZCACK1)
  1235.                     stohdr(0L);
  1236.                 else
  1237.                     stohdr((long)sys2(secbuf));
  1238.                 purgeline();    /* dump impatient questions */
  1239.                 do {
  1240.                     zshhdr(4,ZCOMPL, Txhdr);
  1241.                 }
  1242.                 while (++errors<20 && zgethdr(Rxhdr,1) != ZFIN);
  1243.                 ackbibi();
  1244.                 if (cmdzack1flg & ZCACK1)
  1245.                     exec2(secbuf);
  1246.                 return ZCOMPL;
  1247.             }
  1248.             zshhdr(4,ZNAK, Txhdr); goto again;
  1249. #endif
  1250.         case ZCOMPL:
  1251.             goto again;
  1252.         default:
  1253.             continue;
  1254.         case ZFIN:
  1255.             ackbibi(); return ZCOMPL;
  1256.         case ZCAN:
  1257.             return ERROR;
  1258.         }
  1259.     }
  1260.     return 0;
  1261. }
  1262.  
  1263. /*
  1264.  * Receive 1 or more files with ZMODEM protocol
  1265.  */
  1266. rzfiles()
  1267. {
  1268.     register c;
  1269.  
  1270.     for (;;) {
  1271.         switch (c = rzfile()) {
  1272.         case ZEOF:
  1273.         case ZSKIP:
  1274.             switch (tryz()) {
  1275.             case ZCOMPL:
  1276.                 return OK;
  1277.             default:
  1278.                 return ERROR;
  1279.             case ZFILE:
  1280.                 break;
  1281.             }
  1282.             continue;
  1283.         default:
  1284.             return c;
  1285.         case ERROR:
  1286.             return ERROR;
  1287.         }
  1288.     }
  1289. }
  1290.  
  1291. /*
  1292.  * Receive a file with ZMODEM protocol
  1293.  *  Assumes file name frame is in secbuf
  1294.  */
  1295. rzfile()
  1296. {
  1297.     register c, n;
  1298.     long rxbytes;
  1299.  
  1300.     Eofseen=FALSE;
  1301.     if (procheader(secbuf) == ERROR) {
  1302.         return (tryzhdrtype = ZSKIP);
  1303.     }
  1304.  
  1305.     n = 20; rxbytes = 0l;
  1306.  
  1307.     for (;;) {
  1308. #ifdef SEGMENTS
  1309.         chinseg = 0;
  1310. #endif
  1311.         stohdr(rxbytes);
  1312.         zshhdr(4,ZRPOS, Txhdr);
  1313. nxthdr:
  1314.         switch (c = zgethdr(Rxhdr, 0)) {
  1315.         default:
  1316.             vfile("rzfile: zgethdr returned %d", c);
  1317.             return ERROR;
  1318.         case ZNAK:
  1319.         case TIMEOUT:
  1320. #ifdef SEGMENTS
  1321.             putsec(secbuf, chinseg);
  1322.             chinseg = 0;
  1323. #endif
  1324.             if ( --n < 0) {
  1325.                 vfile("rzfile: zgethdr returned %d", c);
  1326.                 return ERROR;
  1327.             }
  1328.         case ZFILE:
  1329.             zrdata(secbuf, 1024);
  1330.             continue;
  1331.         case ZEOF:
  1332. #ifdef SEGMENTS
  1333.             putsec(secbuf, chinseg);
  1334.             chinseg = 0;
  1335. #endif
  1336.             if (rclhdr(Rxhdr) != rxbytes) {
  1337.                 /*
  1338.                  * Ignore eof if it's at wrong place - force
  1339.                  *  a timeout because the eof might have gone
  1340.                  *  out before we sent our zrpos.
  1341.                  */
  1342.                 errors = 0;  goto nxthdr;
  1343.             }
  1344.             if (closeit()) {
  1345.                 tryzhdrtype = ZFERR;
  1346.                 vfile("rzfile: closeit returned <> 0");
  1347.                 return ERROR;
  1348.             }
  1349.             vfile("rzfile: normal EOF");
  1350.             return c;
  1351.         case ERROR:    /* Too much garbage in header search error */
  1352. #ifdef SEGMENTS
  1353.             putsec(secbuf, chinseg);
  1354.             chinseg = 0;
  1355. #endif
  1356.             if ( --n < 0) {
  1357.                 vfile("rzfile: zgethdr returned %d", c);
  1358.                 return ERROR;
  1359.             }
  1360.             zmputs(Attn);
  1361.             continue;
  1362.         case ZSKIP:
  1363. #ifdef SEGMENTS
  1364.             putsec(secbuf, chinseg);
  1365.             chinseg = 0;
  1366. #endif
  1367.             Modtime = 1;
  1368.             closeit();
  1369.             vfile("rzfile: Sender SKIPPED file");
  1370.             return c;
  1371.         case ZDATA:
  1372.             if (rclhdr(Rxhdr) != rxbytes) {
  1373.                 if ( --n < 0) {
  1374.                     return ERROR;
  1375.                 }
  1376. #ifdef SEGMENTS
  1377.                 putsec(secbuf, chinseg);
  1378.                 chinseg = 0;
  1379. #endif
  1380.                 zmputs(Attn);  continue;
  1381.             }
  1382. moredata:
  1383. #ifdef NeXT
  1384.             [remote transferProgress:rxbytes];
  1385. #endif
  1386.             if (Verbose>1)
  1387.                 fprintf(stderr, "\r%7ld ZMODEM%s    ",
  1388.                   rxbytes, Crc32r?" CRC-32":"");
  1389. #ifdef SEGMENTS
  1390.             if (chinseg >= (1024 * SEGMENTS)) {
  1391.                 putsec(secbuf, chinseg);
  1392.                 chinseg = 0;
  1393.             }
  1394.             switch (c = zrdata(secbuf+chinseg, 1024))
  1395. #else
  1396.             switch (c = zrdata(secbuf, 1024))
  1397. #endif
  1398.             {
  1399.             case ZCAN:
  1400. #ifdef SEGMENTS
  1401.                 putsec(secbuf, chinseg);
  1402.                 chinseg = 0;
  1403. #endif
  1404.                 vfile("rzfile: zgethdr returned %d", c);
  1405.                 return ERROR;
  1406.             case ERROR:    /* CRC error */
  1407. #ifdef SEGMENTS
  1408.                 putsec(secbuf, chinseg);
  1409.                 chinseg = 0;
  1410. #endif
  1411.                 if ( --n < 0) {
  1412.                     vfile("rzfile: zgethdr returned %d", c);
  1413.                     return ERROR;
  1414.                 }
  1415.                 zmputs(Attn);
  1416.                 continue;
  1417.             case TIMEOUT:
  1418. #ifdef SEGMENTS
  1419.                 putsec(secbuf, chinseg);
  1420.                 chinseg = 0;
  1421. #endif
  1422.                 if ( --n < 0) {
  1423.                     vfile("rzfile: zgethdr returned %d", c);
  1424.                     return ERROR;
  1425.                 }
  1426.                 continue;
  1427.             case GOTCRCW:
  1428.                 n = 20;
  1429. #ifdef SEGMENTS
  1430.                 chinseg += Rxcount;
  1431.                 putsec(secbuf, chinseg);
  1432.                 chinseg = 0;
  1433. #else
  1434.                 putsec(secbuf, Rxcount);
  1435. #endif
  1436.                 rxbytes += Rxcount;
  1437.                 stohdr(rxbytes);
  1438.                 zshhdr(4,ZACK, Txhdr);
  1439.                 sendline(XON);
  1440.                 goto nxthdr;
  1441.             case GOTCRCQ:
  1442.                 n = 20;
  1443. #ifdef SEGMENTS
  1444.                 chinseg += Rxcount;
  1445. #else
  1446.                 putsec(secbuf, Rxcount);
  1447. #endif
  1448.                 rxbytes += Rxcount;
  1449.                 stohdr(rxbytes);
  1450.                 zshhdr(4,ZACK, Txhdr);
  1451.                 goto moredata;
  1452.             case GOTCRCG:
  1453.                 n = 20;
  1454. #ifdef SEGMENTS
  1455.                 chinseg += Rxcount;
  1456. #else
  1457.                 putsec(secbuf, Rxcount);
  1458. #endif
  1459.                 rxbytes += Rxcount;
  1460.                 goto moredata;
  1461.             case GOTCRCE:
  1462.                 n = 20;
  1463. #ifdef SEGMENTS
  1464.                 chinseg += Rxcount;
  1465. #else
  1466.                 putsec(secbuf, Rxcount);
  1467. #endif
  1468.                 rxbytes += Rxcount;
  1469.                 goto nxthdr;
  1470.             }
  1471.         }
  1472.     }
  1473. }
  1474.  
  1475. /*
  1476.  * Send a string to the modem, processing for \336 (sleep 1 sec)
  1477.  *   and \335 (break signal)
  1478.  */
  1479. zmputs(s)
  1480. char *s;
  1481. {
  1482.     register c;
  1483.  
  1484.     while (*s) {
  1485.         switch (c = *s++) {
  1486.         case '\336':
  1487.             sleep(1); continue;
  1488.         case '\335':
  1489.             sendbrk(); continue;
  1490.         default:
  1491.             sendline(c);
  1492.         }
  1493.     }
  1494. }
  1495.  
  1496. /*
  1497.  * Close the receive dataset, return OK or ERROR
  1498.  */
  1499. closeit()
  1500. {
  1501.     time_t time();
  1502.  
  1503. #ifndef vax11c
  1504.     if (Topipe) {
  1505.         if (pclose(fout)) {
  1506.             return ERROR;
  1507.         }
  1508.         return OK;
  1509.     }
  1510. #endif
  1511.     if (fclose(fout)==ERROR) {
  1512.         fprintf(stderr, "file close ERROR\n");
  1513.         return ERROR;
  1514.     }
  1515. #ifndef vax11c
  1516.     if (Modtime) {
  1517.         timep[0] = time(NULL);
  1518.         timep[1] = Modtime;
  1519.         utime(Pathname, timep);
  1520.     }
  1521. #endif
  1522.     if ((Filemode&S_IFMT) == S_IFREG)
  1523.         chmod(Pathname, (07777 & Filemode));
  1524.     return OK;
  1525. }
  1526.  
  1527. /*
  1528.  * Ack a ZFIN packet, let byegones be byegones
  1529.  */
  1530. ackbibi()
  1531. {
  1532.     register n;
  1533.  
  1534.     vfile("ackbibi:");
  1535.     Readnum = 1;
  1536.     stohdr(0L);
  1537.     for (n=3; --n>=0; ) {
  1538.         purgeline();
  1539.         zshhdr(4,ZFIN, Txhdr);
  1540.         switch (readline(100)) {
  1541.         case 'O':
  1542.             readline(1);    /* Discard 2nd 'O' */
  1543.             vfile("ackbibi complete");
  1544.             return;
  1545.         case RCDO:
  1546.             return;
  1547.         case TIMEOUT:
  1548.         default:
  1549.             break;
  1550.         }
  1551.     }
  1552. }
  1553.  
  1554.  
  1555.  
  1556. /*
  1557.  * Local console output simulation
  1558.  */
  1559. bttyout(c)
  1560. {
  1561.     if (Verbose || Fromcu)
  1562.         putc(c, stderr);
  1563. }
  1564.  
  1565. #ifndef vax11c
  1566. /*
  1567.  * Strip leading ! if present, do shell escape. 
  1568.  */
  1569. sys2(s)
  1570. register char *s;
  1571. {
  1572.     if (*s == '!')
  1573.         ++s;
  1574.     return system(s);
  1575. }
  1576. /*
  1577.  * Strip leading ! if present, do exec.
  1578.  */
  1579. exec2(s)
  1580. register char *s;
  1581. {
  1582.     if (*s == '!')
  1583.         ++s;
  1584.     mode(0);
  1585.     execl("/bin/sh", "sh", "-c", s);
  1586. }
  1587. #endif
  1588. /* End of rz.c */
  1589.